package org.jsola.hr.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsola.approval.constant.ApproType;
import org.jsola.approval.entity.ApproFlowDO;
import org.jsola.approval.entity.UserApproDO;
import org.jsola.approval.service.IApproListenerService;
import org.jsola.approval.vo.ApproModuleContext;
import org.jsola.approval.vo.UserApproInfoVO;
import org.jsola.approval.vo.UserApproListVO;
import org.jsola.hr.common.DateUtils;
import org.jsola.hr.constant.ApprovalStatusEnum;
import org.jsola.hr.constant.EmpInfoStatus;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.constant.PersonalEventEnum;
import org.jsola.hr.dto.EmpInfoUpdateDTO;
import org.jsola.hr.entity.EmpInfoDO;
import org.jsola.hr.example.PersonalEventExample;
import org.jsola.hr.provider.IApproProviderService;
import org.jsola.hr.service.IEmpChangesService;
import org.jsola.hr.service.IEmpInfoService;
import org.jsola.hr.service.IPersonalEventService;
import org.jsola.hr.task.SendNoticeTask;
import org.jsola.hr.vo.EmpChangesVO;
import org.jsola.hr.vo.EmpInfoVO;
import org.jsola.notice.constant.NoticeConstants;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import static org.jsola.hr.constant.HrConstants.SUBJECT_TYPE_HR_LEAVING;
import static org.jsola.hr.constant.HrConstants.SUBJECT_TYPE_HR_ON_JOB;
import static org.jsola.hr.constant.HrConstants.SUBJECT_TYPE_HR_TRANSFER_DUTY;
import static org.jsola.hr.constant.HrConstants.SUBJECT_TYPE_HR_TURN_STRAIGHT;

/**
 * @author june
 */
@Slf4j
@Primary
@Service("hrEndApproModuleService")
public class HrEndApproModuleService implements IApproListenerService {

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private IEmpChangesService empChangesService;

    @Autowired
    private IApproProviderService approProviderService;

    @Autowired
    private IPersonalEventService personalEventService;

    @Autowired
    private SendNoticeTask sendNoticeTask;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public ApproModuleContext pass(ApproModuleContext approModuleContext) {
        // 值
        TokenUser tokenUser = approModuleContext.getTokenUser();
        UserApproDO userApproDO = approModuleContext.getUserAppro();
        ApproFlowDO approFlowDO = approModuleContext.getApproFlow();

        if (!StringUtils.isEmpty(approModuleContext.getSubjectType())) {
            String empId = approModuleContext.getSubjectId();
            if (SUBJECT_TYPE_HR_ON_JOB.equals(approModuleContext.getSubjectType())) {
                // 入职
                String approType = ApproType.ON_JOB.getValue();
                passEmpAppro(empId, approType, userApproDO.getId(), tokenUser);

                //发送待入职通知
                EmpInfoDO empInfoDO = null;
                try {
                    empInfoDO = empInfoService.selectById(empId);
                    List<UserApproListVO> userApproListVOS = empInfoService.empApproList(empInfoDO.getId(), HrConstants.APPROVE_ON_JOB, tokenUser);
                    if(CollectionUtils.isEmpty(userApproListVOS)){
                        sendNoticeTask.addTask(empInfoDO.getId(), NoticeConstants.PRE_INDUCTION, empInfoDO.getCompanyId(),
                                empInfoDO.getJoinDate(), "人员待入职发送通知", tokenUser);
                    }
                } catch (Exception e) {
                    log.error("待入职审批发送通知失败");
                }

                return approModuleContext;
            } else if (SUBJECT_TYPE_HR_TURN_STRAIGHT.equals(approModuleContext.getSubjectType())) {
                // 转正
                String approType = ApproType.TURN_STRAIGHT.getValue();
                passEmpAppro(empId, approType, userApproDO.getId(), tokenUser);
                //发送待入职通知
                EmpInfoDO empInfoDO = null;
                try {
                    empInfoDO = empInfoService.selectById(empId);
                    empInfoService.sendNotice(empInfoDO,tokenUser);
                } catch (Exception e) {
                    log.error("待转正审批发送通知失败");
                }
                return approModuleContext;
            } else if (SUBJECT_TYPE_HR_TRANSFER_DUTY.equals(approModuleContext.getSubjectType())) {
                // 调岗
                String approType = ApproType.TRANSFER_DUTY.getValue();
                passEmpAppro(empId, approType, userApproDO.getId(), tokenUser);
                try {
                    EmpInfoDO empInfoDO = empInfoService.selectById(empId);
                    empChangesService.sendNotice(empId,empInfoDO.getCompanyId(),new Date(),NoticeConstants.PRE_TRANSFER,tokenUser);
                } catch (Exception e) {
                    log.error("待调岗审批发送通知失败");
                }
                return approModuleContext;
            } else if (SUBJECT_TYPE_HR_LEAVING.equals(approModuleContext.getSubjectType())) {
                // 离职
                String approType = ApproType.LEAVING.getValue();
                passEmpAppro(empId, approType, userApproDO.getId(), tokenUser);
                try {
                    EmpInfoDO empInfoDO = empInfoService.selectById(empId);
                    empChangesService.sendNotice(empId,empInfoDO.getCompanyId(),new Date(),NoticeConstants.PRE_RESIGN ,tokenUser);
                } catch (Exception e) {
                    log.error("待离职审批发送通知失败");
                }
                return approModuleContext;
            } else if("Business".equals(approModuleContext.getSubjectType())){
                String approType = "Business";
                passEmpAppro(empId, approType, userApproDO.getId(), tokenUser);
                EmpInfoDO empInfoDO = empInfoService.selectDOById(empId, tokenUser.getSiteId());
                personalEventService.autoSave(empInfoDO.to(EmpInfoVO.class),tokenUser,PersonalEventExample.BUSINESS,PersonalEventEnum.APPROVAL.getValue(),PersonalEventEnum.APPROVAL.getDesc());

                return approModuleContext;
            }
        }
        if (!StringUtils.isEmpty(approFlowDO.getType()) && !StringUtils.isEmpty(userApproDO.getId())) {
            String approType = approFlowDO.getType();

            if (ApproType.find(approType) != null) {
                // 是入转调离中的,员工id放在表单中
                List<String> empIdList = getEmpIdByForm(userApproDO, tokenUser);
                if (CollectionUtils.isEmpty(empIdList)) {
                    return approModuleContext;
                }
                for (String empId : empIdList) {
                    passEmpAppro(empId, approType, userApproDO.getId(), tokenUser);
                }
            }
        }
        return approModuleContext;
    }

    /**
     * 通过员工审批
     *
     * @param empId       员工id
     * @param approType   审批类型
     * @param userApproId 用户审批申请id
     * @param tokenUser   当前用户
     */
    private void passEmpAppro(String empId, String approType, String userApproId, TokenUser tokenUser) {
        // 员工
        EmpInfoVO empInfoVO = empInfoService.selectById(empId, tokenUser.getSiteId());
        if (Objects.isNull(empInfoVO)) {
            return;
        }
        if (ApproType.ON_JOB.getValue().equals(approType)) {
            // 入职
            // 通过用户审批
            empInfoService.passEmpAppro(empId, ApproType.ON_JOB.getValue(), tokenUser);
            log.info("用户入职审批通过,修改员工状态,empId:{},userApproId:{}", empId, userApproId);
        } else if (ApproType.TURN_STRAIGHT.getValue().equals(approType)) {
            // 转正
            empInfoService.passEmpAppro(empId, ApproType.TURN_STRAIGHT.getValue(), tokenUser);
            log.info("用户转正审批通过,修改员工状态,empId:{},userApproId:{}", empId, userApproId);

            // 修改员工信息
            EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
            empInfoUpdateDTO.setId(empId);
            empInfoUpdateDTO.setStatus(EmpInfoStatus.HAS_ENTRY.getValue());

            // 变更
            EmpChangesVO empChangesVO = empChangesService.findByUserApproId(userApproId, tokenUser.getSiteId());
            if (!Objects.isNull(empChangesVO)) {
                // 转正时间
                empInfoUpdateDTO.setTurnStraightDate(empChangesVO.getRegularDate());
                // 获取明天时间0点
                Date dateTomorrow = DateUtils.getTomorrow();

                // 转正时间明天之前,直接转正
                if (empChangesVO.getRegularDate().before(dateTomorrow)) {
                    // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
                    empInfoUpdateDTO.setChangeStatus(0);
                    // 正式类型（1：试用期，2：已转正）
                    empInfoUpdateDTO.setFormalType(2);
                    empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_DISABLE.getValue());
                } else {
                    // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
                    empInfoUpdateDTO.setChangeStatus(1);
                    // 正式类型（1：试用期，2：已转正）
                    empInfoUpdateDTO.setFormalType(1);
                    // 入职时间今天之后,转正日期当天转为正式员工
                    empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_SUCCESS.getValue());
                }
            } else {
                // 转正时间
                empInfoUpdateDTO.setTurnStraightDate(new Date());
                // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
                empInfoUpdateDTO.setChangeStatus(0);
                // 正式类型（1：试用期，2：已转正）
                empInfoUpdateDTO.setFormalType(2);
                empInfoUpdateDTO.setApprovalStatus(ApprovalStatusEnum.APPRO_DISABLE.getValue());
            }
            empInfoService.update(empInfoUpdateDTO, tokenUser);
        } else if (ApproType.TRANSFER_DUTY.getValue().equals(approType)) {
            // 调岗
            empInfoService.passEmpAppro(empId, ApproType.TRANSFER_DUTY.getValue(), tokenUser);
            log.info("用户调岗审批通过,修改员工状态,empId:{},userApproId:{}", empId, userApproId);
        } else if (ApproType.LEAVING.getValue().equals(approType)) {
            // 离职
            empInfoService.passEmpAppro(empId, ApproType.LEAVING.getValue(), tokenUser);
            log.info("用户离职审批通过,修改员工状态,empId:{},userApproId:{}", empId, userApproId);
        }
    }

    /**
     * 入转调离根据表单获取empId
     *
     * @param userApproDO 用户审批申请
     * @param tokenUser   当前用户
     * @return 员工id集合
     */
    private List<String> getEmpIdByForm(UserApproDO userApproDO, TokenUser tokenUser) {
        if (Objects.isNull(userApproDO)) {
            return null;
        }
        if (!StringUtils.isEmpty(userApproDO.getSubjectId())) {
            return Collections.singletonList(userApproDO.getSubjectId());
        }
        // 获取用户的员工id
        String userApproId = userApproDO.getId();
        String formId = "applyUser";
        UserApproInfoVO userApproInfoVO = approProviderService.selectUserApproInfoByFormId(userApproId, formId, tokenUser.getSiteId());
        if (Objects.isNull(userApproInfoVO)) {
            formId = "employee";
            userApproInfoVO = approProviderService.selectUserApproInfoByFormId(userApproId, formId, tokenUser.getSiteId());
        }
        if (Objects.isNull(userApproInfoVO)) {
            return null;
        }
        // 当时选择的员工
        String empIds = userApproInfoVO.getValue();
        if (StringUtils.isEmpty(empIds)) {
            return null;
        }
        return Arrays.asList(empIds.split(","));
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public ApproModuleContext reject(ApproModuleContext approModuleContext) {

        // 值
        TokenUser tokenUser = approModuleContext.getTokenUser();
        UserApproDO userApproDO = approModuleContext.getUserAppro();
        ApproFlowDO approFlowDO = approModuleContext.getApproFlow();

        if (!StringUtils.isEmpty(approModuleContext.getSubjectType())) {
            String empId = userApproDO.getSubjectId();
            if (SUBJECT_TYPE_HR_ON_JOB.equals(approModuleContext.getSubjectType())) {
                // 入职
                String approType = ApproType.ON_JOB.getValue();
                rejectEmpAppro(empId, approType, userApproDO.getId(), tokenUser);
                return approModuleContext;
            } else if (SUBJECT_TYPE_HR_TURN_STRAIGHT.equals(approModuleContext.getSubjectType())) {
                // 转正
                String approType = ApproType.TURN_STRAIGHT.getValue();
                rejectEmpAppro(empId, approType, userApproDO.getId(), tokenUser);
                return approModuleContext;
            } else if (SUBJECT_TYPE_HR_TRANSFER_DUTY.equals(approModuleContext.getSubjectType())) {
                // 调岗
                String approType = ApproType.TRANSFER_DUTY.getValue();
                rejectEmpAppro(empId, approType, userApproDO.getId(), tokenUser);
                return approModuleContext;
            } else if (SUBJECT_TYPE_HR_LEAVING.equals(approModuleContext.getSubjectType())) {
                // 离职
                String approType = ApproType.LEAVING.getValue();
                rejectEmpAppro(empId, approType, userApproDO.getId(), tokenUser);
                return approModuleContext;
            }
        }

        if (!StringUtils.isEmpty(approFlowDO.getType()) && !StringUtils.isEmpty(userApproDO.getId())) {
            String approType = approFlowDO.getType();

            if (ApproType.find(approType) != null) {
                // 是入转调离中的,员工id放在表单中
                List<String> empIdList = getEmpIdByForm(userApproDO, tokenUser);
                if (CollectionUtils.isEmpty(empIdList)) {
                    return approModuleContext;
                }
                for (String empId : empIdList) {
                    rejectEmpAppro(empId, approType, userApproDO.getId(), tokenUser);
                }
            }
        }
        return approModuleContext;
    }

    /**
     * 拒绝员工审批
     *
     * @param empId       员工id
     * @param approType   审批类型
     * @param userApproId 用户审批申请id
     * @param tokenUser   当前用户
     */
    private void rejectEmpAppro(String empId, String approType, String userApproId, TokenUser tokenUser) {
        // 员工
        EmpInfoVO empInfoVO = empInfoService.selectById(empId, tokenUser.getSiteId());
        if (Objects.isNull(empInfoVO)) {
            return;
        }
        // 修改员工信息
        EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
        empInfoUpdateDTO.setId(empId);
        // 员工变动状态（0：当前无变动，1：转正中，2：调岗中，3： 离职中）
        empInfoUpdateDTO.setChangeStatus(0);

        // 入职
        if (ApproType.ON_JOB.getValue().equals(approType)) {
            // 通过用户审批
            empInfoService.rejectEmpAppro(empId, ApproType.ON_JOB.getValue(), tokenUser);
            log.info("用户入职审批被拒绝,修改员工状态,empId:{},userApproId:{}", empId, userApproId);
        } else if (ApproType.TURN_STRAIGHT.getValue().equals(approType)) {
            empInfoUpdateDTO.setStatus(EmpInfoStatus.HAS_ENTRY.getValue());
            // 转正
            empInfoService.rejectEmpAppro(empId, ApproType.TURN_STRAIGHT.getValue(), tokenUser);
            log.info("用户转正被拒绝,修改员工状态,empId:{},userApproId:{}", empId, userApproId);
        } else if (ApproType.TRANSFER_DUTY.getValue().equals(approType)) {
            empInfoUpdateDTO.setStatus(EmpInfoStatus.HAS_ENTRY.getValue());
            // 调岗
            empInfoService.rejectEmpAppro(empId, ApproType.TRANSFER_DUTY.getValue(), tokenUser);
            log.info("用户调岗审批被拒绝,修改员工状态,empId:{},userApproId:{}", empId, userApproId);
        } else if (ApproType.LEAVING.getValue().equals(approType)) {
            empInfoUpdateDTO.setStatus(EmpInfoStatus.HAS_ENTRY.getValue());
            // 离职
            empInfoService.rejectEmpAppro(empId, ApproType.LEAVING.getValue(), tokenUser);
            log.info("用户离职审批被拒绝,修改员工状态,empId:{},userApproId:{}", empId, userApproId);
        }
        // 修改员工信息
        empInfoService.update(empInfoUpdateDTO, tokenUser);
    }

    @Override
    public ApproModuleContext revoke(ApproModuleContext approModuleContext) {
        // todo 删除员工

        return approModuleContext;
    }

    @Override
    public Boolean isSupport(String subjectType, String subjectId) {
        if (SUBJECT_TYPE_HR_ON_JOB.equals(subjectType)) {
            // 入职
            return true;
        } else if (SUBJECT_TYPE_HR_TURN_STRAIGHT.equals(subjectType)) {
            // 转正
            return true;
        } else if (SUBJECT_TYPE_HR_TRANSFER_DUTY.equals(subjectType)) {
            // 调岗
            return true;
        } else if (SUBJECT_TYPE_HR_LEAVING.equals(subjectType)) {
            // 离职
            return true;
        }
        return false;
    }
}




